package com.lqk.netty.handler.chat;

import com.lqk.netty.common.protobuf.MessageModule;
import com.lqk.netty.handler.HeartBeatHandler;
import com.lqk.netty.handler.ServerHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.handler.timeout.IdleStateHandler;
import java.util.concurrent.TimeUnit;

/**
 * @author liqiankun@nnuo.com
 * @date 2023/3/31 13:55
 * @description
 **/
public class ChatServerChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        socketChannel.pipeline().addLast(new ProtobufVarint32FrameDecoder());
        socketChannel.pipeline().addLast(new ProtobufDecoder(MessageModule.Message.getDefaultInstance()));
        socketChannel.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
        socketChannel.pipeline().addLast(new ProtobufEncoder());
        // ====================== 增加心跳支持 start    ======================
        // 针对客户端，如果在30秒没有向服务端发送读写心跳(ALL)，则主动断开
        // 如果是读空闲或者写空闲，不处理,读写空闲超过30秒，则断开连接
        /**
         * 1. IdleStateHandler 是 netty 提供的处理空闲状态的处理器
         * 2. long readerIdleTime ：表示多长时间没有读（Sever端没有读取Client发送的数据），就会发送一个心跳检测包，检测是否还是连接状态
         * 3. long writerIdleTime ：表示多长时间没有写（Sever端没有写数据发送给Client端），就会发送一个心跳检测包，检测是否还是连接状态
         * 4. long allIdleTime ：表示多长时间没有读写，就会发送一个心跳检测包，检测是否还是连接状态
         * 5. TimeUnit unit ：时间单位
         * 6. 当Channel有一段时间没有执行读、写或两者操作时触发IdleStateEvent 。
         * 7. 当 IdleStateHandler 出发后，就会传递给管道的下一个 Handler 去处理，通过调用（触发）下一个 Handler 的 userEventTriggered，
         * 在该方法中处理 IdleStateHandler （读空闲、写空闲、读写空闲）
         */
        socketChannel.pipeline().addLast(new IdleStateHandler(0, 0, 30, TimeUnit.SECONDS));
        // 自定义的空闲状态检测
        socketChannel.pipeline().addLast(new ChatServerHeartBeatHandler());
        // ====================== 增加心跳支持 end    ======================
        socketChannel.pipeline().addLast(new ChatNettyServerHandler());
    }
}
